package com.company.nuwa.mybatis.generator.plugins;

import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.util.StringUtility;

import java.text.MessageFormat;
import java.util.Properties;

/**
 * <p>Hystrix </p>
 *
 * @author lili
 * @version 1.0: FacadePlugin
 * @date 2023/9/18 17:36
 */
public class HystrixPlugin {
    public static GeneratedJavaFile hystrixPluginFile(IntrospectedTable introspectedTable,
                                                      Context context,
                                                      String targetProject) {
        Properties contextProperties = context.getProperties();
        String applicationName = contextProperties.getProperty("applicationName");
        String contextPath = contextProperties.getProperty("contextPath");
        String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        StringBuilder builder = new StringBuilder();
        FullyQualifiedJavaType mapperType = new FullyQualifiedJavaType(
            introspectedTable.getMyBatis3JavaMapperType());
        TopLevelClass requestClass = new TopLevelClass(builder.delete(0, builder.length())
            .append(mapperType.getPackageName().replace(".mapper", "").replace("domain", "api"))
            .append(".").append("hystrix").append(".").append(domainObjectName)
            .append("FeignClientHystrix").toString());
        requestClass.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType interfaceType = new FullyQualifiedJavaType(
            MessageFormat.format("FallbackFactory<{0}Facade>", domainObjectName));
        requestClass.addSuperInterface(interfaceType);
        context.getCommentGenerator().addJavaFileComment(requestClass);
        String basePage = mapperType.getPackageName();

        //添加domain的import
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".api",".*")));
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".request",".*")));
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".dto",".*")));
        requestClass.addImportedType("org.apache.commons.lang3.exception.ExceptionUtils");
        requestClass.addImportedType("org.springframework.cloud.openfeign.FallbackFactory");
        requestClass.addImportedType("org.springframework.stereotype.Component");
        requestClass.addImportedType("java.util.List");
        requestClass.addImportedType("com.company.nuwa.common.utils.JsonUtils");
        //request+dto
        requestClass.addImportedType("com.company.nuwa.common.domain.HttpMessageResult");
        requestClass.addImportedType("com.github.pagehelper.PageInfo");
        requestClass.addImportedType("lombok.extern.slf4j.Slf4j");
        requestClass.addImportedType("com.company.nuwa.common.enumration.GlobalCallbackEnum");
        requestClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Generated"));
        //添加Feign的注解
        requestClass.addAnnotation("@Slf4j");
        requestClass.addAnnotation("@Component");
        requestClass.addJavaDocLine("/**");
        String remarks = introspectedTable.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                requestClass.addJavaDocLine(" * <p>" + remarkLine + "</p>");
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(" * @author ").append(System.getProperties().getProperty("user.name"));
        requestClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * ").append("@version 1.0:")
            .append(introspectedTable.getFullyQualifiedTable().getDomainObjectName())
            .append("FeignClientHystrix").append(".java");
        requestClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * @date ");
        sb.append(ApiExtPluginUtils.getDateString());
        requestClass.addJavaDocLine(sb.toString());
        requestClass.addJavaDocLine(" */");
        //增加方法
        Method createMethod = new Method("create");
        createMethod.setVisibility(JavaVisibility.PUBLIC);
        Parameter addParameter = new Parameter(new FullyQualifiedJavaType("Throwable"), "cause");
        createMethod.addParameter(addParameter);
        createMethod.setReturnType(new FullyQualifiedJavaType(domainObjectName + "Facade"));
        createMethod.addJavaDocLine("/**");
        createMethod.addJavaDocLine(
            "* Returns an instance of the fallback appropriate for the given cause.");
        createMethod.addJavaDocLine("* @param cause cause of an exception.");
        createMethod.addJavaDocLine("* @return fallback");
        createMethod.addJavaDocLine(" */");
        createMethod.addBodyLine("log.error(\"["+introspectedTable.getRemarks()+"{}]熔断\",ExceptionUtils.getStackTrace(cause));");
        createMethod.addBodyLine(addMethodBody(domainObjectName));
        requestClass.addMethod(createMethod);
        GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(requestClass,
            targetProject,
            context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
            context.getJavaFormatter());
        return generatedJavaFile;
    }

    @lombok.SneakyThrows
    public static String addMethodBody(String domainObjectName) {
        //初始化代码
        ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("/templates");
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        //获取模板
        Template t = gt.getTemplate("hystrix.java.btl");
        t.binding("domainObjectName", domainObjectName);
        //渲染结果
        String str = t.render();
        System.out.println(str);
        return str;
    }

}
